package cn.kbyue.filesystem.rest;

import org.springframework.core.io.ByteArrayResource;
import org.springframework.core.io.Resource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;

/**
 * @author XL
 * @version 0.1
 * @date 2021/11/16 21:50
 *
 * 参考资源(不限)：
 *
 * https://www.cnblogs.com/asche/p/10205745.html
 */
@RestController
@RequestMapping("file")
public class FileResource {

    private static final String BASE_DIR = "D://upload//";

    @PostMapping("upload")
    public ResponseEntity<String> upload(@RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            return ResponseEntity.badRequest().body("请上传文件");
        }
        File dest = new File(BASE_DIR + file.getOriginalFilename());
        if (!dest.getParentFile().exists()) {
            boolean maked = dest.getParentFile().mkdirs();
            if (!maked) {
                return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("服务器文件资源无法访问");
            }
        }
        try {
            file.transferTo(dest);
        } catch (IOException e) {
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("文件上传失败");
        }
        return ResponseEntity.ok(dest.getAbsolutePath());
    }

    /**
     *
     * @param path
     * @param response
     * @throws UnsupportedEncodingException
     */
    @GetMapping("download/{path}")
    public void download(@PathVariable("path") String path, HttpServletResponse response) throws UnsupportedEncodingException {
        File dest = new File(BASE_DIR + path);
        String filename = dest.getName();
        if (dest.exists()) {
            // 12738927752503940292.jpg
            response.setContentType("image/jpeg");
            response.setCharacterEncoding("UTF-8");
            // response.setContentType("application/force-download");
            response.setHeader("Content-Disposition", String.format("attachment;fileName=%s", URLEncoder.encode(filename, "UTF-8")));

            try (
                    BufferedInputStream br = new BufferedInputStream(new FileInputStream(dest));
                    OutputStream os = response.getOutputStream()
            ) {
                byte[] buffer = new byte[1024];
                int i = br.read(buffer);
                while (i != -1) {
                    os.write(buffer);
                    i = br.read(buffer);
                }
                os.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 访问示例： http://localhost:10008/file/download/jpg?fileName=12738927752503940292
     * 服务器文件夹中存在图片：D://testfile//12738927752503940292.jpg
     *
     * @param fileName exam: 12738927752503940292
     * @return
     * @throws IOException
     */
    @GetMapping("download/jpg")
    public ResponseEntity<Resource> res(String fileName) throws IOException {
        File dest = new File(BASE_DIR + fileName + ".jpg");
        if (dest.exists()) {
            try(
                    FileInputStream fis = new FileInputStream(dest);
            ) {
                Resource resource = new ByteArrayResource(toByteArray(fis));
                return ResponseEntity.ok()
                        .contentType(MediaType.IMAGE_JPEG)
                        .header(HttpHeaders.CONTENT_DISPOSITION, String.format("attachment;fileName=%s", dest.getName()))
                        .body(resource);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            }
        }
        return ResponseEntity.badRequest().body(null);
    }

    private byte[] toByteArray(InputStream in){
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        try {
            byte[] bytes = new byte[1024];
            int n;
            while ((n = in.read(bytes)) != -1){
                byteArrayOutputStream.write(bytes, 0, n);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return byteArrayOutputStream.toByteArray();
    }

}
